﻿///////////////////////////////////////////////////////////////////////////////
//
//  This source is part of the  "Managed Task Framework.NET Runtime"  (MTF.NET Runtime).
//
//
//  Copyright (c) 2011, Multicore Consulting Limited (UK)
//  All rights reserved.
//  http://www.multicoreconsulting.co.uk
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions
//  are met:
//
//  -  Redistributions of source code must retain the above copyright
//     notice, this list of conditions and the following disclaimer.
//  -  Redistributions in binary form must reproduce the above copyright
//     notice, this list of conditions and the following disclaimer in
//     the documentation and/or other materials provided with the
//     distribution.
//  -  Neither the name of Multicore Consulting Limited nor the names of
//     its contributors may be used to endorse or promote products
//     derived from this software without specific prior written
//     permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
//  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
//  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
//  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
//  COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
//  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
//  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
//  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
//  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
//  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
//  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
//  POSSIBILITY OF SUCH DAMAGE.
//
///////////////////////////////////////////////////////////////////////////////

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MTFOrg.MTF.MTFCore
{
    /// <summary>
    /// Defines an event that is produced by a queue.
    /// </summary>
    public class QueueEvent : Event
    {
        /// <summary>
        /// Constant value representing no affinity.
        /// </summary>
        public const int NO_AFFINITY = -1;

        public enum CancelState
        {
            None,
            CancelToBack,
            CancelToFront
        }

        /// <summary>
        /// Item produced by the queue.
        /// </summary>
        protected object m_Item;

        /// <summary>
        /// Queue from which this item was sourced.
        /// </summary>
        protected QueueType m_SourceQueue;

        /// <summary>
        /// Flag indicating whether the event should be canceled.
        /// </summary>
        protected CancelState m_Cancel;

        /// <summary>
        /// Specifies thread associated with the data item.
        /// </summary>
        protected int m_ThreadAffinity;

        /// <summary>
        /// Specifies whether the store that produced the event imposes thread affinity.
        /// </summary>
        protected bool m_HasAffinity;

        /// <summary>
        /// Sequence number.
        /// </summary>
        protected int m_SequenceNumber;

        /// <summary>
        /// Gets the item produced by the queue.
        /// </summary>
        public object Item
        {
            get { return m_Item; }
            set { m_Item = value; }
        }

        /// <summary>
        /// Gets the source queue for the item.
        /// </summary>
        public QueueType SourceQueue
        {
            get { return m_SourceQueue; }
        }

        /// <summary>
        /// Gets and sets the thread affinity.
        /// </summary>
        public int ThreadAffinity
        {
            get { return m_ThreadAffinity; }
            set { m_ThreadAffinity = value; }
        }

        /// <summary>
        /// Gets whether the associated store has thread affinity.
        /// </summary>
        public bool HasAffinity
        {
            get { return m_HasAffinity; }
        }

        /// <summary>
        /// Gets the sequence number.
        /// </summary>
        public int SequenceNumber
        {
            get { return m_SequenceNumber; }
        }

        /// <summary>
        /// Sets the event to a back canceled state.
        /// </summary>
        public void Cancel()
        {
            Cancel(false);
        }

        /// <summary>
        /// Sets the event to a front or back canceled state.
        /// </summary>
        /// <param name="cancelToFront">true to cancel to the front, false to cancel to the back</param>
        public void Cancel(bool cancelToFront)
        {
            m_Cancel = cancelToFront ? CancelState.CancelToFront : CancelState.CancelToBack;
        }

        /// <summary>
        /// Determines if the event has been canceled.
        /// </summary>
        /// <returns>true if canceled, otherwise false</returns>
        public bool IsCanceled()
        {
            return (m_Cancel != CancelState.None);
        }

        /// <summary>
        /// Determines if the event has been canceled to the front.
        /// </summary>
        /// <returns>true if canceled to front, otherwise false</returns>
        public bool IsCanceledToFront()
        {
            return (m_Cancel == CancelState.CancelToFront);
        }

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="item">Item produced by the queue</param>
        public QueueEvent(object item, QueueType sourceQueue, bool hasAffinity, int sequenceNumber)
        {
            m_Item = item;
            m_SourceQueue = sourceQueue;
            m_Cancel = CancelState.None;
            m_ThreadAffinity = NO_AFFINITY;
            m_HasAffinity = hasAffinity;
            m_SequenceNumber = sequenceNumber;
        }

        /// <summary>
        /// Converts an event to an event array
        /// </summary>
        /// <returns>Event array containing QueueEvent</returns>
        public EventArray ToEventArray()
        {
            return new EventArray(this);
        }
    }
}
